/**
 * Copyright 2010 MiSSO4J author(s)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sjsso.cas.servlet;

import static org.sjsso.Constant.APPID;
import static org.sjsso.Constant.CALLBACK_URL;
import static org.sjsso.Constant.MSG;
import static org.sjsso.Constant.NONCE;
import static org.sjsso.Constant.NONCES;
import static org.sjsso.Constant.PASSWORD;
import static org.sjsso.Constant.PREV_URL;
import static org.sjsso.Constant.SESSIONS;
import static org.sjsso.Constant.SESSION_USER;
import static org.sjsso.Constant.UID;
import static org.sjsso.Constant.USERNAME;

import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.sjsso.model.User;

@SuppressWarnings("serial")
public class LoginServlet extends BaseServlet {

	private static SecureRandom random = new SecureRandom();

	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		HttpSession session = request.getSession();
		User user = (User) session.getAttribute(SESSION_USER);
		String appid = request.getParameter(APPID);
		String cburl = request.getParameter(CALLBACK_URL);
		String prev = request.getParameter(PREV_URL);

		// Make its an authentication request
		if (!isSSORequest(appid, cburl))
			return;

		if (user == null) {
			session.setAttribute(APPID, appid);
			session.setAttribute(CALLBACK_URL, cburl);
			session.setAttribute(PREV_URL, prev);
			request.getRequestDispatcher("WEB-INF/jsp/" + appid + "_login.jsp")
					.include(request, response);
		} else {
			response.sendRedirect(getMainPageUrl(user, cburl, prev));
		}
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		HttpSession session = request.getSession();
		String appid = (String) session.getAttribute(APPID);
		String cburl = (String) session.getAttribute(CALLBACK_URL);
		String prev = (String) session.getAttribute(PREV_URL);
		String username = request.getParameter(USERNAME);
		String password = request.getParameter(PASSWORD);

		if (!validCredential(username, password)) {
			request.setAttribute(MSG, "Login failed.");
			request.getRequestDispatcher("WEB-INF/jsp/" + appid + "_login.jsp")
					.include(request, response);
		} else if (isSSORequest(appid, cburl)) {
			User user = register(username,request);

			response.sendRedirect(getMainPageUrl(user, cburl, prev));
		}
	}

	protected boolean validCredential(String username, String password) {
		boolean result = false;
		if ((username != null) && (password != null) && username.length() > 0
				&& password.length() > 0) {
			result = username.equals(password);
		}
		return result;
	}

	private String getMainPageUrl(User user, String cburl, String prev) {
		String url = cburl + "?" + UID + "=" + user.getUsername() + "&" + NONCE
				+ "=" + generateNonce(user) + "&" + PREV_URL + "=" + prev;
		return url;
	}

	private String generateNonce(User user) {
		String nonce = "";
		Map<String, String> nounces = getNonceMap();
		do {
			nonce = new BigInteger(130, random).toString(32);
		} while (null != nounces.get(nonce));

		addToNonceList(nonce, user.getToken());
		return nonce;
	}

	private User register(String username, HttpServletRequest request) {
		HttpSession session = request.getSession();
		User user = new User();
		user.setUsername(username);
		user.setToken(session.getId());
		user.setIp(request.getRemoteAddr());

		// track session id
		addToSessionMap(user);

		session.setAttribute(SESSION_USER, user);
		session.setAttribute(CALLBACK_URL, null);
		return user;
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		Map<String, User> sessionList = new HashMap<String, User>();
		Map<String, String> nonceMap = new HashMap<String, String>();
		ServletContext context = config.getServletContext();
		context.setAttribute(SESSIONS, sessionList);
		context.setAttribute(NONCES, nonceMap);
	}

	private boolean isSSORequest(String appid, String cburl) {
		// Can still be improved
		return (appid != null && cburl != null);
	}
}